#include "pagination.h"

#include <QPainter>
#include <QStyleOption>
#include <QListView>
#include <QKeyEvent>

#include <QDebug>

#define MINIMUM_PAGE 1
#ifndef MAX_BUTTON_COUNT
#define MAX_BUTTON_COUNT 6
#endif

#ifndef PAGE_STEP
#define PAGE_STEP 5
#endif

//q:303103757 and v:qt5_qt6

/***
 * 如何使用
 * Pagination必须基于一个QWidget创建，否则会引发错误。

Pagination* pa = new Pagination(QWidget*);
设置总页数
Pagination需要设置一个总的页数，来初始化页码。

pa->SetTotalItem(count);
设置可选的每页数量
可以通过传给Pagination一个整形数组，来设置每页显示的条目数。

int args[4] = {1, 100, 200, 300};
pa->SetItemPerPage(args, 4);
刷新配置参数
当上面参数设置完成后，需要调用一次Refresh来刷新配置。

pa->Refresh();
获取当前页数的变化
当Pagination当前的页码发生变化时，会产生一个PageChanged信号，原型如下：

void GotoPageSignals(int nPage);
其中，nPage代表要跳转的页数。

获取每页条目数的变化
当Pagination的每页数量发生变化时，会产生一个NumberPerPageChanged信号，原型如下：

void NumberPerPageChanged(int nCount);
其中，nCount表示最新的每页条目数量。
***/

namespace kepen {
namespace core {

Pagination::Pagination(QWidget *parent) :
    QWidget(parent),
    m_nCurrentPage(MINIMUM_PAGE),
    m_nMaxPage(MINIMUM_PAGE),
    m_nDisplayPage(0)
{
    setObjectName("PageImplRx");
    setAutoFillBackground(true);
    setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);
    setMinimumSize(600, 50);
    Init();
}

Pagination::~Pagination()
{
    if(m_pHPageLayout)
    {
        delete m_pHPageLayout;
        m_pHPageLayout = nullptr;
    }
    qDebug() << __FILE__ << __LINE__ << "~Pagination";
}

void Pagination::SetTotalItem(int nTotal)
{

    int EachPage = m_pItemEachPage->GetSizePage();
    if(EachPage > 0)
    {
        m_nMaxPage = nTotal / EachPage;
        if(nTotal % EachPage > 0) ++m_nMaxPage;
        if(m_nMaxPage <= 0) m_nMaxPage = MINIMUM_PAGE;
        // 如果m_nMaxPage大于MAX_BUTTON_COUNT，则只构建7个按钮，头、尾，中间5个
        if(m_nMaxPage > MAX_BUTTON_COUNT) m_nDisplayPage = MAX_BUTTON_COUNT + 1;
        else m_nDisplayPage = m_nMaxPage;
    }
     m_pTotalItem->SetTotal(nTotal,m_nMaxPage);
}

void Pagination::SetItemPerPage(int *args, int size)
{
    m_pItemEachPage->SetSizePageData(args, size);
    int EachPage = m_pItemEachPage->GetSizePage();
    if(EachPage > 0)
    {
        int nTotal = m_pTotalItem->GetTotal();
        m_nMaxPage = nTotal / EachPage;
        if(nTotal % EachPage > 0) ++m_nMaxPage;
        if(m_nMaxPage <= 0) m_nMaxPage = MINIMUM_PAGE;
        // 如果m_nMaxPage小于MAX_BUTTON_COUNT，则不变。

        // 如果m_nMaxPage大于MAX_BUTTON_COUNT，则只构建7个按钮，头、尾，中间5个
        if(m_nMaxPage > MAX_BUTTON_COUNT) m_nDisplayPage = MAX_BUTTON_COUNT + 1;
        else m_nDisplayPage = m_nMaxPage;
    }
}

void Pagination::Refresh()
{
    Reload();
}

void Pagination::ChangeView(int currentPage)
{
    /****************************************************************
     *                     改变页数的几种情形
     * 1、显示页数（m_nDisplay）小于等于MAX_BUTTON_COUNT，则该函数不做任何处理。
     * 2、显示页数（m_nDisplay）大于MAX_BUTTON_COUNT，开始处理
     *   (1).初始(currentPage < MAX_BUTTON_COUNT).
     *      ① currentPage != 5,  [1] 2 3 4 5 6 ... max
     *      ② currentPage == 5,  此时应当放到(2)去处理，因为此时已经形成 1 ... 3 4 [5]的情况
     *   (2).(currentPage >= MAX_BUTTON_COUNT)。
     *      ① 两个省略号中间(currentPage < max - 3)：1 ... 3 4 [5] 6 7 ... max
     *      ② 后省略号后面(currentPage >= max - 3)： 1 ... 4 5 [6] 7 8 max
     * ***************************************************************/
    if(currentPage == MINIMUM_PAGE)
        m_pBtnLeft->setDisabled(true); // 当前第一页，禁用左按钮
    else
        m_pBtnLeft->setDisabled(false); // 开启右按钮
    if(currentPage == m_nMaxPage)
        m_pBtnRight->setDisabled(true); // 最后一页，禁用右按钮
    else
        m_pBtnRight->setDisabled(false); // 开启左按钮
    if(m_nDisplayPage <= MAX_BUTTON_COUNT)
        return; // 1情况
    if(currentPage < MAX_BUTTON_COUNT && currentPage != MAX_BUTTON_COUNT - 1) // 2.1情况
    {
        // 页面情况 1 2 3 4 5 6 ... max
        for(unsigned long long i = 0; i < m_vecPageBtn.size(); i++)
        {
            QPushButton* btn = m_vecPageBtn[i];
            if(btn->isHidden()) btn->show();
            if(i == m_vecPageBtn.size() - 1)
                btn->setText(QString::number(m_nMaxPage));
            else
                btn->setText(QString::number(i + 1));
            btn->adjustSize();
            if(btn->text().toInt() == currentPage)
                btn->setChecked(true);
            else
                btn->setChecked(false);
        }
        // 显示后省略号，屏蔽前省略
        if(!m_pBtnOmitFront->isHidden())
            m_pBtnOmitFront->hide();
        if(m_pBtnOmitBack->isHidden())
            m_pBtnOmitBack->show();
    }
    else
    {
        if(currentPage < m_nMaxPage - 3) // 2.2.1情况
        {
            // 页面情况 currentPage - 2, currentPage - 1, [currentPage], currentPage + 1, currentPage + 2
            int value = - 2;
            for(unsigned long long i = 1; i <= 5; i++)
            {
                QPushButton* btn = m_vecPageBtn[i];
                btn->setText(QString::number(currentPage + value++));
                btn->adjustSize();
                if(btn->text().toInt() == currentPage) btn->setChecked(true);
                else btn->setChecked(false);
            }
            // 开启两边省略号
            if(m_pBtnOmitFront->isHidden()) m_pBtnOmitFront->show();
            if(m_pBtnOmitBack->isHidden()) m_pBtnOmitBack->show();
        }
        else // 2.2.2情况
        {
            // 页面情况 1 ... max - 5, max - 4, [max - 3], max - 2, max - 1, max
            // 除了第一个不变，其它全变
            for(unsigned long long i = 1; i < m_vecPageBtn.size(); i++)
            {
                QPushButton* btn = m_vecPageBtn[i];
                btn->setText(QString::number(m_nMaxPage - MAX_BUTTON_COUNT + i));
                btn->adjustSize();
                if(btn->text().toInt() == currentPage) btn->setChecked(true);
                else btn->setChecked(false);
            }
            // 显示前省略号，屏蔽后省略
            if(m_pBtnOmitFront->isHidden()) m_pBtnOmitFront->show();
            if(!m_pBtnOmitBack->isHidden()) m_pBtnOmitBack->hide();
        }
    }
}

QPushButton *Pagination::GetPageItem(int nPos)
{
    return dynamic_cast<QPushButton*>(m_pHPageLayout->itemAt(nPos)->widget());
}

void Pagination::Init()
{
    setObjectName("pagination");
    setStyleSheet(QStringLiteral("QWidget#pagination{background-color:transparent;}"));
    m_pHMainLayout = new QHBoxLayout(this);
    m_pHPageLayout = new QHBoxLayout;
    m_pTotalItem = new TotalItem(this);
    m_pItemEachPage = new SizePageCombox(this);
    m_pGotoItem = new GotoPageInput(this);
    m_pBtnLeft = new QPushButton("<", this);
    m_pBtnRight = new QPushButton(">", this);
    m_pBtnOmitFront = new QPushButton(this);
    m_pBtnOmitBack = new QPushButton(this);
    m_vecPageBtn.reserve(10);
    // m_pBtnOmitFront->setStyleSheet(QStringLiteral("QPushButton{border:none;background-color:transparent;background:background-position:center;}"
    //                                               "QPushButton:hover{{background-color:white;color:black;background-position:center;}"));
    // m_pBtnOmitBack->setStyleSheet(QStringLiteral("QPushButton{border:none;background-color:transparent;background-position:center;}"
    //                                              "QPushButton:hover{background:background-color:white;color:black;background-position:center;}"));
    m_nCurrentPage = 1;
    int args[4] = { 100, 200, 300, 400 };
    SetItemPerPage(args, sizeof (args) / sizeof (int));

    m_pBtnOmitFront->hide();
    m_pBtnOmitBack->hide();
    int btnWidth = 0;
    for(int i = 0; i < m_nDisplayPage; i++)
    {
        if(i == 1) m_pHPageLayout->addWidget(m_pBtnOmitFront);
        if(i == m_nMaxPage - 2 && i != 0) m_pHPageLayout->addWidget(m_pBtnOmitBack);
        QPushButton* btn = new QPushButton(QString::number(i + 1), this);
        btn->setCheckable(true);
        m_pHPageLayout->addWidget(btn);
        m_vecPageBtn.emplace_back(btn);
        connect(btn, &QPushButton::clicked, this, &Pagination::btn_page_clicked);
        btnWidth += btn->width();
    }

    for(auto & x : findChildren<QPushButton*>())
    {
        x->setMinimumSize(32, 32);
        x->setCursor(QCursor(Qt::PointingHandCursor));
        if(x != m_pBtnOmitFront && x != m_pBtnOmitBack)
        {
            x->setStyleSheet(QStringLiteral("QPushButton{font-size:15px;font-weight:bold;border:none;background-color:transparent;color:black;}"
                                            "QPushButton:hover{color:#409EFF;}"
                                            "QPushButton:pressed{color:#409EFF;}"
                                            "QPushButton:checked{color:#409EFF;}"
                                            "QPushButton:disabled{color:#BCBEC2;}"));
        }
    }

    ChangeView(m_nCurrentPage);

    m_pHMainLayout->addWidget(m_pTotalItem);
    m_pHMainLayout->addWidget(m_pItemEachPage, Qt::AlignCenter);
    m_pHMainLayout->addWidget(m_pBtnLeft);
    m_pHMainLayout->addLayout(m_pHPageLayout);
    m_pHMainLayout->addWidget(m_pBtnRight);
    m_pHMainLayout->addWidget(m_pGotoItem);
    m_pHMainLayout->addStretch();

    // 上一页
    connect(m_pBtnLeft, &QPushButton::clicked, this, [this](){
        if(m_nCurrentPage - 1 < 0) m_nCurrentPage = 1;
        else --m_nCurrentPage;
        ChangeView(m_nCurrentPage);
        emit GotoPageSignals(m_nCurrentPage);
    });

    // 下一页
    connect(m_pBtnRight, &QPushButton::clicked, this, [&](){
        if(m_nCurrentPage + 1 > m_nMaxPage) m_nCurrentPage = m_nMaxPage;
        else ++m_nCurrentPage;
        ChangeView(m_nCurrentPage);
        emit GotoPageSignals(m_nCurrentPage);
    });

    // 左省略号，当作快退，即退m_nDisplay页
    connect(m_pBtnOmitFront, &QPushButton::clicked, this, [&](){
        if(m_nCurrentPage - PAGE_STEP < MINIMUM_PAGE) m_nCurrentPage = MINIMUM_PAGE;
        else m_nCurrentPage -= PAGE_STEP;
        ChangeView(m_nCurrentPage);
        emit GotoPageSignals(m_nCurrentPage);
    });

    // 右省略号，当作快进，即进m_nDisplay页
    connect(m_pBtnOmitBack, &QPushButton::clicked, this, [&](){
        if(m_nCurrentPage + PAGE_STEP > m_nMaxPage) m_nCurrentPage = m_nMaxPage;
        else m_nCurrentPage += PAGE_STEP;
        ChangeView(m_nCurrentPage);
        emit GotoPageSignals(m_nCurrentPage);
    });

    // 前往第N页
    connect(m_pGotoItem, &GotoPageInput::GotoPage, this, [&](int nPage){
        if(nPage > m_nMaxPage) nPage = m_nMaxPage;
        if(nPage < MINIMUM_PAGE) nPage = MINIMUM_PAGE;
        if(nPage + 1 > m_nMaxPage) m_nCurrentPage = m_nMaxPage;
        else m_nCurrentPage = nPage;
        ChangeView(m_nCurrentPage);
        emit GotoPageSignals(m_nCurrentPage);
    });

    // 每页条码变化
    connect(m_pItemEachPage, &SizePageCombox::EachPageItemChanged, this, [&](int nCount){
        int EachPage = m_pItemEachPage->GetSizePage();
        if(EachPage > 0)
        {
            int nTotal = m_pTotalItem->GetTotal();
            m_nMaxPage = nTotal / EachPage;
            if(nTotal % EachPage > 0)
                ++m_nMaxPage;
            if(m_nMaxPage <= 0)
                m_nMaxPage = MINIMUM_PAGE;
            // 如果m_nMaxPage小于MAX_BUTTON_COUNT，则不变。

            // 如果m_nMaxPage大于MAX_BUTTON_COUNT，则只构建7个按钮，头、尾，中间5个
            if(m_nMaxPage > MAX_BUTTON_COUNT)
                m_nDisplayPage = MAX_BUTTON_COUNT + 1;
            else
                m_nDisplayPage = m_nMaxPage;
        }
        Reload();
        emit NumberPerPageChanged(nCount);
    });
}

void Pagination::paintEvent(QPaintEvent *event)
{
    QStyleOption opt;
    opt.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
    QWidget::paintEvent(event);
}

QPushButton *Pagination::FindPage(int nIndex) const
{
    QWidget* tmp;
    for(int i = 0; i < m_pHPageLayout->count(); i++)
    {
        QLayoutItem* item = m_pHPageLayout->itemAt(i);
        if(item)
        {
            tmp = item->widget();
            if(tmp)
            {
                QPushButton* btn = qobject_cast<QPushButton*>(tmp);
                if((btn) && btn->text().compare(QString::number(nIndex)) == 0)
                {
                    return btn;
                }
            }

        }
    }
    return nullptr;
}

void Pagination::ClearPage()
{
    QWidget* tmp;
    QLayoutItem* item;
    QSpacerItem *itemSpace;
    int sz = m_pHPageLayout->count();
    for(int i = 0; i < sz; i++)
    {


        if((item = m_pHPageLayout->takeAt(0)))
        {
            if((tmp = item->widget()))
            {
                m_pHPageLayout->removeWidget(tmp);
                delete tmp;
                tmp = nullptr;
            }

            delete item;
            item = nullptr;

        }else if((itemSpace = item->spacerItem())){
            m_pHPageLayout->removeItem(item);
            delete itemSpace;
            itemSpace = nullptr;
            delete item;
            item = nullptr;
        }

    }
    m_vecPageBtn.clear();
}

void Pagination::Reload()
{
    ClearPage();
    int lastPage = m_nCurrentPage;
    m_nCurrentPage = 1;
    m_pBtnOmitFront = new QPushButton(this);
    m_pBtnOmitBack = new QPushButton(this);
    // m_pBtnOmitFront->setStyleSheet(QStringLiteral("QPushButton{border:none;background-color:transparent;background-position:center;}"
    //                                               "QPushButton:hover{background-color:#ddd;background-position:center;}"));
    // m_pBtnOmitBack->setStyleSheet(QStringLiteral("QPushButton{border:none;background-color:transparent;background-position:center;}"
    //                                              "QPushButton:hover{background-color:#ddd;background-position:center;}"));


    m_pBtnOmitFront->setCursor(QCursor(Qt::PointingHandCursor));
    m_pBtnOmitBack->setCursor(QCursor(Qt::PointingHandCursor));
    m_pBtnOmitFront->hide();
    m_pBtnOmitBack->hide();
    for(int i = 0; i < m_nDisplayPage; i++)
    {
        QPushButton* btn = new QPushButton(QString::number(i + 1), this);
        btn->setCheckable(true);
        m_pHPageLayout->addWidget(btn);

        btn->setMinimumSize(32, 32);
        btn->setCursor(QCursor(Qt::PointingHandCursor));
        btn->setStyleSheet(QStringLiteral("QPushButton{font-size:15px;font-weight:bold;border:none;background-color:transparent;color:black;}"
                                          "QPushButton:hover{color:#409EFF;}"
                                          "QPushButton:pressed{color:#409EFF;}"
                                          "QPushButton:checked{color:#409EFF;}"
                                          "QPushButton:disabled{color:#BCBEC2;}"));
        connect(btn, &QPushButton::clicked, this, &Pagination::btn_page_clicked);
        m_vecPageBtn.emplace_back(btn);
    }
    m_pHPageLayout->insertWidget(1, m_pBtnOmitFront);
    m_pHPageLayout->insertWidget(m_pHPageLayout->count() - 1, m_pBtnOmitBack);

    // 初始化一次界面
    ChangeView(m_nCurrentPage);

    if(lastPage > m_nMaxPage) // 上次停留的页数大于现在的最大页数
        m_nCurrentPage = m_nMaxPage; // 直接变成当前最大页数
    else
        m_nCurrentPage = lastPage; // 否则还是保持当前页数
    ChangeView(m_nCurrentPage); // 再次刷新下当前界面

    // 左省略号，当作快退，即退PAGE_STEP页
    connect(m_pBtnOmitFront, &QPushButton::clicked, this, [&](){
        if(m_nCurrentPage - PAGE_STEP < MINIMUM_PAGE) m_nCurrentPage = MINIMUM_PAGE;
        else m_nCurrentPage -= PAGE_STEP;
        ChangeView(m_nCurrentPage);
        emit GotoPageSignals(m_nCurrentPage);
    });

    // 右省略号，当作快进，即进PAGE_STEP页
    connect(m_pBtnOmitBack, &QPushButton::clicked, this, [&](){
        if(m_nCurrentPage + PAGE_STEP > m_nMaxPage) m_nCurrentPage = m_nMaxPage;
        else m_nCurrentPage += PAGE_STEP;
        ChangeView(m_nCurrentPage);
        emit GotoPageSignals(m_nCurrentPage);
    });
}

void Pagination::btn_page_clicked()
{
    QPushButton* btn = qobject_cast<QPushButton*>(sender());
    if(btn && btn != m_pBtnOmitFront && btn != m_pBtnOmitBack)
    {
        QString str = btn->text();
        int nIndex = str.toInt(); // 要跳转的页数
        QPushButton* page = FindPage(m_nCurrentPage);  // 找到当前页数按钮
        if(page) page->setChecked(false); // 取消选中
        QPushButton* nPage = FindPage(nIndex);
        if(nPage) nPage->setChecked(true);
        m_nCurrentPage = nIndex;
        ChangeView(m_nCurrentPage);
        emit GotoPageSignals(nIndex);
    }
}


}
}
